<?php
namespace app\spider\service;
use QL\QueryList;
use QL\Ext\CurlMulti;
use QL\Ext\AbsoluteUrl;
use think\Db;

class QueryFilmService
{
    /**
     * @var CurlMulti
     */
    private $curl = null;

    private $params = [];

    private $curl_opt = [
        'opt' => [
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_AUTOREFERER => true,
            CURLOPT_USERAGENT =>'Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 UBrowser/5.5.6125.14 Safari/537.36',
            CURLOPT_TIMEOUT => 10,
            CURLOPT_CONNECTTIMEOUT => 10,
            CURLOPT_RETURNTRANSFER => true,
        ],

        //设置线程数
        'maxThread' => 10,

        //设置最大尝试数
        'maxTry' => 3,

        // 缓存选项很容易被理解，缓存使用url来识别。如果使用缓存类库不会访问网络而是直接返回缓存。
        //'cache' => ['enable' => false, 'compress' => false, 'dir' => null, 'expire' =>86400, 'verifyPost' => false]
    ];


    public function __construct($sites = [])
    {
        $ql = QueryList::getInstance();
        $ql->use(CurlMulti::class);
        $ql->use(AbsoluteUrl::class);

        $params = [];
        $urls = [];
        foreach($sites as $key=>$value){
            $value['list_reg'] = $this->isJson($value['list_reg']);
            $value['content_reg'] = $this->isJson($value['content_reg']);
            $value['page_reg'] = $this->isJson($value['page_reg']);
            $urls[] = $value['list_url'] ? $value['list_url'] : $value['site_url'];
            $params[$value['site_url']] = $value;
        }

        $this->params = $params;
        $this->curl = $ql->curlMulti($urls);
    }

    public function fuck(){
        $_service = $this;
        $this->curl->success(function (QueryList $ql, CurlMulti $curl, $r) use ($_service) {
            $this->callbackList($ql, $curl, $r);
        })->error(function ($errorInfo,CurlMulti $curl){
            echo "Current url:{$errorInfo['info']['url']} \r\n";
            print_r($errorInfo['error']);
        })->start($this->curl_opt);
    }


    public function addUrls($urls) {
        $this->curl->add($urls);
    }



    public function callbackList(QueryList $ql, CurlMulti $curl, $r){
        echo $r['info']['url'], "\n";
        preg_match('/^(https?:\/\/)?[\d\w]{0,}\.?[\d\w]+\.\w+\/?/i', $r['info']['url'],$baseUrl);
        $baseUrl[0] = rtrim($baseUrl[0],'/');

        $list_reg = $this->params[$baseUrl[0]]['list_reg'];
        $page_reg = $this->params[$baseUrl[0]]['page_reg'];

        $gather_action = $this->params[$baseUrl[0]]['gather_action'] ? $this->params[$baseUrl[0]]['gather_action'] : '\\app\\spider\\service\\content\\ContentService';

        $charset = strtoupper($this->params[$baseUrl[0]]['charset']);
        $ql->html($r['body']);
        if($charset != 'UTF-8'){
            $ql->encoding('UTF-8', $charset);
        }

        $list = $ql->rules([
            'link'  => [$list_reg['url'][0], $list_reg['url'][1]],
            'title' => $list_reg['title']
        ])->query()->getData(function ($item) use($ql, $baseUrl, $curl, $gather_action, $r)  {
            //使用帮助函数单独转换某个链接
            $item['link'] = absolute_url($item['link'], $baseUrl[0], $r['info']['url']);
            $sql = "INSERT IGNORE db_gather_url(`hash_unique`,`gahter_url`) VALUES(crc32(concat('{$item['link']}',1)),'{$item['link']}')";
            $is_exit = Db::table('db_gather_url')->execute($sql);
            if ($is_exit && class_exists($gather_action)) {
                $curl->addTasks([$item['link']], function ($r) use ($ql, $curl,$item, $gather_action){
                    $gather_action = new $gather_action($this->params);
                    $gather_action->process($ql, $curl, $r, $item);
                });
            }
            return false;
        })->all();

        foreach ($list as $key => $value) {
            if (!$value) unset($list[$key]);
        }
        if(is_array($list) && count($list) > 0){
            $page = $ql->rules([
                'page'=>[$page_reg[0], $page_reg[1]]
            ])->query()->getData(function ($item) use($ql, $baseUrl, $curl, $r) {
                //使用帮助函数单独转换某个链接
                $item['page'] = absolute_url($item['page'], $baseUrl[0], $r['info']['url']);
                return $item;
            })->flatten()->take(1)->all();

            if($page && $page[0]){
                $this->addUrls(array($page[0]));
            }else{
                echo "no next page \n";
            }
        }else{
            echo "no data \n";
        }

        $ql->destruct();
    }


    protected function  isJson($str){
        $res = json_decode($str,true);
        return is_null($res) ? $str :$res;
    }

}
